﻿using LdtDataEngin.ModuleDetail.BaseModule.UIEExtract;
using LdtJudge.DataEngine.Common;
using LdtJudge.DataEngine.Common.DateAssemble;
using LdtJudge.DataEngine.DataBaseStores;
using LdtJudge.DataEngine.Model.DataModel.SysCommon;
using LdtJudge.DataEngine.Model.ElmentModel;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace LdtDataEngin.ModuleDetail.BaseModule
{
    /// <summary>
    /// 事实要素节点机器学习提取类
    /// </summary>
    public class FactNodeMachLearnClass
    {
        #region 基础信息加载
        //上下文数据
        public DataContext _dataContext;

        //事实要素节点调用uie配置内容
        public string uieConfig;

        //UIE提取模型
        private readonly UIEServiceProxy uieService = new UIEServiceProxy();

        //要素配置
        public Dictionary<string, ElementConfigModel> Diccofig { get; set; }

        //案由数据集合
        public List<CaseCauseModel> casecauseList { get; set; }
        #endregion

        /// <summary>
        /// 通过机器学习提取节点
        /// </summary>
        /// <param name="originalText">原文</param>
        /// <param name="parentGuid">父级Guid</param>
        /// <param name="nodePath">节点路径</param>
        /// <param name="listValue">节点原文提取值</param>
        /// <returns></returns>
        public List<NodeModel> NodeExtractThroughML(string originalText, string parentGuid, string nodePath, IList<string> listValue)
        {
            List<NodeModel> result = new List<NodeModel>();
            UieModelHandleClass uieModelHandle = new UieModelHandleClass();
            nodePath = nodePath.Replace("\\", "/");
            //调用UIE模型提取接口
            string modelCode = "wxjsz_qsyjs";
            string xmlConfig = string.Empty;
            if (!string.IsNullOrWhiteSpace(uieConfig))
                xmlConfig = HttpHelp.EnDataBase64(uieConfig);
            var param = new
            {
                modelCode = modelCode,
                content = originalText,
                xmlConfig = xmlConfig
            };
            string paramStr = JsonConvert.SerializeObject(param);
            _dataContext.InteractiveShow.LogShow($"案由要素节点【{nodePath}】的原文【{originalText}】调用UIE模型提取入参：{paramStr}");

            XmlDocument modelXml = new XmlDocument();
            if (_dataContext.DataLayerAns.dicCauseMLValue.ContainsKey(paramStr))
            {
                _dataContext.InteractiveShow.LogShow($"案由要素节点【{nodePath}】存在缓存，缓存值：{_dataContext.DataLayerAns.dicCauseMLValue[paramStr].OuterXml}");
                modelXml = _dataContext.DataLayerAns.dicCauseMLValue[paramStr];

            }
            else
            {
                var uieResponse = uieService.UieRecognition(modelCode, originalText, xmlConfig);
                _dataContext.InteractiveShow.LogShow($"案由要素节点【{nodePath}】调用UIE模型提取结果：{JsonConvert.SerializeObject(uieResponse)}");
                if (uieResponse.Body != null && uieResponse.Body.Any())
                {
                    modelXml = uieModelHandle.UieModelToXml(uieResponse.Body, "案由要素");
                    _dataContext.DataLayerAns.dicCauseMLValue.Add(paramStr, modelXml);
                    _dataContext.InteractiveShow.LogShow($"案由要素节点【{nodePath}】UIE模型提取数据转换xml：{modelXml.OuterXml}");
                }

            }
            if (modelXml != null && !string.IsNullOrEmpty(modelXml.OuterXml))
            {
                var nodeModels = XmlToNodeMode(modelXml, parentGuid, originalText, listValue);
                if (nodeModels != null && nodeModels.Any())
                {
                    var nodeList = nodeModels.Where(x => x.NodePath.Contains(nodePath)).ToList();
                    if (nodeList != null && nodeList.Any())
                    {
                        foreach (var nodeItem in nodeList.Where(x => x.NodePath == nodePath))
                        {
                            nodeItem.ParentGuidID = parentGuid;
                        }
                        result = nodeList;
                    }
                }
            }

            //var uieResponse = uieService.UieRecognition(modelCode, originalText, xmlConfig);
            //_dataContext.InteractiveShow.LogShow($"案由要素节点【{nodePath}】调用UIE模型提取结果：{JsonConvert.SerializeObject(uieResponse)}");
            //if(uieResponse.Body!=null && uieResponse.Body.Any())
            //{
            //    //将UIE模型返回数据转换为xml
            //    XmlDocument modelXml = uieModelHandle.UieModelToXml(uieResponse.Body, "案由要素");
            //    _dataContext.InteractiveShow.LogShow($"案由要素节点【{nodePath}】UIE模型提取数据转换xml：{modelXml.OuterXml}");
            //    //将xml转换为NodeModel数据集合
            //    var nodeModels = XmlToNodeMode(modelXml, parentGuid, originalText, listValue);
            //    if (nodeModels != null && nodeModels.Any())
            //    {
            //        var nodeList = nodeModels.Where(x => x.NodePath.Contains(nodePath)).ToList();
            //        if (nodeList != null && nodeList.Any())
            //        {
            //            foreach (var nodeItem in nodeList.Where(x => x.NodePath == nodePath))
            //            {
            //                nodeItem.ParentGuidID = parentGuid;
            //            }
            //            result = nodeList;
            //        }
            //    }
            //}
            return result;
        }

        /// <summary>
        /// 将xml转换为NodelModel
        /// </summary>
        /// <param name="xmlDocument">XmlDocument结构</param>
        /// <param name="parentGuid">父级Guid</param>
        /// <param name="orgText">原文</param>
        /// <param name="listValue">节点原文提取值</param>
        /// <returns></returns>
        private List<NodeModel> XmlToNodeMode(XmlDocument xmlDocument, string parentGuid, string orgText, IList<string> listValue)
        {
            List<NodeModel> result = new List<NodeModel>();
            foreach (XmlNode xmlNode in xmlDocument.ChildNodes)
            {
                NodeChangeModel(xmlNode, result, "/案由要素", "", orgText, listValue);
            }
            return result;
        }

        /// <summary>
        /// 组装NodeMode数据
        /// </summary>
        /// <param name="xmlNode">XmlDocument的xmlNode节点</param>
        /// <param name="nodeModelList">NodeModel集合</param>
        /// <param name="xpath">节点Xpath路径</param>
        /// <param name="parentGuid">父级Guid</param>
        /// <param name="orgText">原文</param>
        /// <param name="listValue">节点原文提取值</param>
        private void NodeChangeModel(XmlNode xmlNode, List<NodeModel> nodeModelList, string xpath, string parentGuid, string orgText, IList<string> listValue)
        {
            var cause = casecauseList.FirstOrDefault(x => x.XmlPath == xpath && x.CC_Name == xmlNode.Name);

            NodeModel nodeModel = new NodeModel();
            nodeModel.ModelType = 1;
            nodeModel.GuidID = Snowflake.Instance().GetId().ToString();
            nodeModel.NodeID = cause?.CC_ID;
            nodeModel.ParentGuidID = parentGuid;
            nodeModel.NodePath = cause?.XmlPath;
            nodeModel.NodeName = cause?.CC_Name;
            nodeModel.OriginalText = orgText;
            nodeModel.ExtOriginalText = listValue;
            nodeModel.ExtValue = listValue;
            if (listValue != null && listValue.Count > 0)
            {
                nodeModel.IsNullExtOriginalText = true;
            }
            nodeModel.ElementConfigModel = Diccofig.ContainsKey(nodeModel.NodePath) ? Diccofig[nodeModel.NodePath] : null;
            nodeModel.ElementCommWhere = null;
            nodeModelList.Add(nodeModel);
            foreach (XmlAttribute attribute in xmlNode.Attributes)
            {
                var attrName = attribute.Name;
                if (attrName != "id")
                {
                    var attrCause = casecauseList.FirstOrDefault(x => x.CC_NodeType == 12 && x.CC_Name == attrName && x.AllParentId.Contains(cause.CC_ID));
                    NodeModel nodeAttrModel = new NodeModel();
                    nodeAttrModel.ModelType = 2;
                    nodeAttrModel.GuidID = Snowflake.Instance().GetId().ToString();
                    nodeAttrModel.NodeID = attrCause?.CC_ID;
                    nodeAttrModel.ParentGuidID = nodeModel.GuidID;
                    nodeAttrModel.NodePath = GetXmlPath(attrCause?.XmlPath);
                    nodeAttrModel.NodeName = attrCause?.CC_Name;
                    nodeAttrModel.OriginalText = orgText;
                    nodeAttrModel.ExtOriginalText = new List<string> { attribute.Value };
                    nodeAttrModel.ExtValue = new List<string> { attribute.Value };
                    nodeAttrModel.IsNullExtOriginalText = true;
                    nodeAttrModel.ElementConfigModel = Diccofig.ContainsKey(nodeAttrModel.NodePath) ? Diccofig[nodeAttrModel.NodePath] : null;
                    nodeAttrModel.ElementCommWhere = null;
                    ImplementConfig(nodeAttrModel, nodeModelList);
                    nodeModelList.Add(nodeAttrModel);
                }
            }
            foreach (XmlNode node in xmlNode.ChildNodes)
            {
                string childNodePath = $"{nodeModel.NodePath}/{node.Name}";
                NodeChangeModel(node, nodeModelList, childNodePath, nodeModel.GuidID, orgText, listValue);
            }

        }

        /// <summary>
        /// 转换xpath
        /// </summary>
        /// <param name="xmlpath">xpath路径</param>
        private string GetXmlPath(string xmlpath)
        {
            string path = string.Empty;
            if (!string.IsNullOrWhiteSpace(xmlpath))
            {
                path = xmlpath.Substring(xmlpath.IndexOf("案由要素"));
                path = "/" + path;
            }
            return path;
        }

        /// <summary>
        /// 转字典类型
        /// </summary>
        /// <param name="nodeModel">需要转字典节点Model</param>
        /// <param name="listnodemode">所有节点Model</param>
        /// <returns></returns>
        private List<NodeModel> ImplementConfig(NodeModel nodeModel, List<NodeModel> listnodemode)
        {
            List<NodeModel> listNodeModel = new List<NodeModel>();
            nodeModel.ExtOriginalText = nodeModel.ExtOriginalText.Where(a => a != null).ToList();
            List<NodeModel> listvalues = new List<NodeModel>();
            listvalues.Add(nodeModel);
            if (nodeModel.IsNullExtOriginalText || NodeModeParent(nodeModel, listnodemode))
            {
                #region 配置处理
                ElementConfigModel elementConfigModel = new ElementConfigModel();
                elementConfigModel = nodeModel.ElementConfigModel;

                if (elementConfigModel != null)
                {
                    #region 转字典处理

                    if (!string.IsNullOrEmpty(elementConfigModel.sourceType))
                    {
                        for (int i = 0; i < nodeModel.ExtOriginalText.Count; i++)
                        {
                            if (nodeModel.ExtOriginalText[i] != null)
                            {
                                string returnvalue =
                                    LdtJudge.DataEngine.Common.CommHelp.DictionariesConver.GetArgumentValue(
                                        elementConfigModel.sourceType, elementConfigModel.sourceContent,
                                        nodeModel.ExtOriginalText[i]);
                                if (!string.IsNullOrWhiteSpace(returnvalue))
                                {
                                    nodeModel.ExtOriginalText[i] = returnvalue;
                                }
                            }
                        }
                    }
                    #endregion

                    #region 进行内容去重
                    if (nodeModel.ExtOriginalText.Count > 0)
                    {
                        nodeModel.ExtOriginalText = nodeModel.ExtOriginalText.Distinct().ToList();
                    }
                    #endregion

                    #region fieldType 值类型处理
                    if (!string.IsNullOrEmpty(elementConfigModel.fieldType))
                    {
                        string fieldType = elementConfigModel.fieldType;
                        for (int i = 0; i < nodeModel.ExtOriginalText.Count; i++)
                        {
                            switch (fieldType)
                            {
                                //时间格式转换 天，日
                                case "datetime":
                                    Match dateMatch = Regex.Match(nodeModel.OriginalText,
                                        @"[\d零O一二三四五六七八九十]{1,4}年[\d零O一二三四五六七八九十]{1,3}月[\d零O一二三四五六七八九十]{1,3}日(?=.*?" +
                                        nodeModel.ExtOriginalText[i] + ")");
                                    string relatDateStr = dateMatch.Value; //关联的日期值
                                    nodeModel.ExtOriginalText[i] =
                                        CommonFormat.FormatDateCompute(relatDateStr, nodeModel.ExtOriginalText[i]);
                                    break;
                                //转中文日期
                                case "ChineseDate":
                                    nodeModel.ExtOriginalText[i] =
                                        DateTimeFormat.ConvertToDate(nodeModel.ExtOriginalText[i]);
                                    break;
                                //转换标准时间
                                case "StandardDate":
                                    nodeModel.ExtOriginalText[i] =
                                        ConvertStingToDateTime.ConvertToStandardDate(nodeModel.ExtOriginalText[i]);
                                    break;
                                //转换标准时间
                                case "Standardamount":
                                    //nodeModel.ExtOriginalText[i] = BaseBianliang.SetStandardamount(nodeModel.ExtOriginalText[i]);
                                    nodeModel.ExtOriginalText[i] =
                                        CommonFormat.FormatDataField(fieldType, nodeModel.ExtOriginalText[i]);
                                    break;
                                default:
                                    nodeModel.ExtOriginalText[i] =
                                        CommonFormat.FormatDataField(fieldType, nodeModel.ExtOriginalText[i]);
                                    break;
                            }
                        }
                    }
                    #endregion
                    string formatType = elementConfigModel.formatType;
                    if (string.IsNullOrEmpty(formatType))
                    {
                        #region checkType数据格式转换
                        if (!string.IsNullOrEmpty(elementConfigModel.checkType))
                        {
                            string checkType = elementConfigModel.checkType;
                            //单选模式处理
                            if (checkType == "radio")
                            {
                                while (nodeModel.ExtOriginalText.Count > 1)
                                {
                                    nodeModel.ExtOriginalText.RemoveAt(1);
                                }
                            }
                            else if (checkType == "check")
                            {
                                string value = "";
                                foreach (string text in nodeModel.ExtOriginalText)
                                {
                                    value += text + ",";
                                }
                                ///清除原有的数据
                                nodeModel.ExtOriginalText.Clear();
                                nodeModel.ExtOriginalText.Add(value.TrimEnd(','));
                            }
                            else
                            {
                                if (nodeModel.ExtOriginalText.Count > 1)
                                {
                                    for (int i = 1; i < nodeModel.ExtOriginalText.Count; i++)
                                    {
                                        NodeModel nodeModelnew = new NodeModel();
                                        nodeModelnew.GuidID = Snowflake.Instance().GetId().ToString();
                                        nodeModelnew.ElementCommWhere = nodeModel.ElementCommWhere;
                                        nodeModelnew.ElementConfigModel = nodeModel.ElementConfigModel;
                                        nodeModelnew.ExtOriginalText.Add(nodeModel.ExtOriginalText[i]);
                                        nodeModelnew.IsNullExtOriginalText = nodeModel.IsNullExtOriginalText;
                                        nodeModelnew.ModelType = nodeModel.ModelType;
                                        nodeModelnew.NodeID = nodeModel.NodeID;
                                        nodeModelnew.NodeName = nodeModel.NodeName;
                                        nodeModelnew.NodePath = nodeModel.NodePath;
                                        nodeModelnew.OriginalText = nodeModel.OriginalText;
                                        nodeModelnew.ParentGuidID = nodeModel.ParentGuidID;
                                        nodeModelnew.SourcType = nodeModel.SourcType;
                                        listNodeModel.Add(nodeModelnew);
                                        listvalues.Add(nodeModelnew);
                                    }
                                }
                            }
                        }
                        #endregion
                    }
                }
                #endregion
            }
            else if (!nodeModel.IsNullExtOriginalText && nodeModel.ElementConfigModel != null)
            {
                string convertValue = LdtJudge.DataEngine.Common.CommHelp.DictionariesConver.GetArgumentValue(
                    nodeModel.ElementConfigModel.sourceType, nodeModel.ElementConfigModel.sourceContent, "");
                if (!string.IsNullOrWhiteSpace(convertValue))
                {
                    nodeModel.IsNullExtOriginalText = true;
                    nodeModel.ExtOriginalText.Add(convertValue);
                }
            }
            return listvalues;
        }

        /// <summary>
        /// 根据父级计算是否是人员节点
        /// </summary>
        /// <param name="nodeModel">父级节点Model</param>
        /// <param name="listNodeModel">所有节点Model</param>
        /// <returns></returns>
        private bool NodeModeParent(NodeModel nodeModel, List<NodeModel> listNodeModel)
        {
            NodeModel nodeModelP = listNodeModel.FirstOrDefault(a => a.GuidID == nodeModel.ParentGuidID);
            if (nodeModel.ElementConfigModel == null)
                return false;
            if (nodeModel.ElementConfigModel.isPersonNode == 1 || nodeModel.ElementConfigModel.formatType != null)
            {
                if (nodeModelP.IsNullExtOriginalText)
                {
                    return true;
                }
            }
            return false;
        }
    }
}
